#ifndef __H_MSG_COMPONENT_H__
#define __H_MSG_COMPONENT_H__

#include <vector>
#include <map>
#include "concurrentqueue.h"
#include "lightweightsemaphore.h"
#include "Component.h"

#include "Packet.h"
#include "globalDefine.h"
#include "log.h"

// http server
#include "handler.h"
#include "http.h"
#include "buffer.h"
#include "listener.h"
#include "mainworker.h"

typedef struct HttpData{
    uint32 request_id;
    std::string method;
    std::string target;
    std::string body;
    std::string ip;
    int port;
    
    std::string fullpath;
    std::map<std::string,std::string> params;
    std::vector<std::string> sub_paths;
} HttpData;

typedef struct CurlData{
    uint32 callback_id;
    std::string body;
    bool isOK;
    long code;
}CurlData;

class MainHandler : public HiveNS::Handler
{
public:
    MainHandler();
    virtual ~MainHandler();

    // from Handler
	virtual void onReceiveHttp(HiveNS::Http* pHttp);
	virtual void onCurlResponse(HiveNS::Buffer* pBuffer, uint32 nodeID, uint32 callbackID, bool isRequestOK, long code);
	virtual void onCloseHttp(HiveNS::Http* pHttp);
	virtual void onCloseListener(HiveNS::Listener* pListener);
};


struct MsgData
{
	std::uint16_t svtype = 0;
	std::uint32_t svid = 0;
	bool from_client = false;
	std::int32_t cmd = 0;
    std::uint32_t uuid = 0;
	std::string data;

	MsgData() = default;
	MsgData(const MsgData& that)
	{
		svtype = that.svtype;
		svid = that.svid;
		from_client = that.from_client;
		cmd = that.cmd;
		uuid = that.uuid;
		data = that.data;
	}
	MsgData(MsgData&& that)
	{
		svtype = std::move(that.svtype);
		svid = std::move(that.svid);
		from_client = std::move(that.from_client);
		cmd = std::move(that.cmd);
		uuid = std::move(that.uuid);
		data = std::move(that.data);
	}
	MsgData& operator=(const MsgData& that)
	{
		svtype = that.svtype;
		svid = that.svid;
		from_client = that.from_client;
		cmd = that.cmd;
		uuid = that.uuid;
		data = that.data;
		return *this;
	}
	MsgData& operator=(MsgData&& that)
	{
		svtype = std::move(that.svtype);
		svid = std::move(that.svid);
		from_client = std::move(that.from_client);
		cmd = std::move(that.cmd);
		uuid = std::move(that.uuid);
		data = std::move(that.data);
		return *this;
	}
};

class MsgRouter
{
public:
    MsgRouter();
    ~MsgRouter();

public:
    virtual bool Init(int port, const std::string& param);
    virtual void Reload();
    virtual void Release(); 
    
public:
    void ReceiveTimerData(int timer_id);

public:
    void ReceiveMsgData(MsgData&& data);
    
public:
    void ReceiveHttpData(HttpData& data);

    // 返回response给请求方
    bool httpServerBack(uint32 request_id, int status_code,
        const std::map<std::string, std::string>& header_map, const std::string& body);

public:
    bool sendHttpPOST(const std::string& url, const std::string& body, const std::map<std::string, std::string>& headers, uint32& callbackID);
    bool sendHttpGET(const std::string& url, const std::string& body, const std::map<std::string, std::string>& headers, uint32& callbackID);

    void ReceiveCurlData(CurlData& data);

protected:
    void EventHandle();
protected:
    int OnProcessPacket(MsgData&& msg_data);
    int OnProcessTimer(int Timerid);
    void OnGetMessage(HttpData&& data);
    // curl接收到返回结果
    void OnCurlResponse(uint32 callback_id, std::string& body, bool isOK, long code);

public:
    void BindHttpHandle(std::string method, std::string target, std::function<void(HttpData&& data)> handle);
    void AddCurlEvent(std::int32_t event_id, std::function<void(std::string&, bool)> event_handle);
public:
    inline void BindTimer(std::int32_t timer, std::function<int(int)> handler) {
        m_timer_handler[timer] = handler;
    }
    inline void BindMsg(std::int32_t msg, std::function<void(MsgData&&)>handler) {
        m_msg_handler[msg] = handler;
    }

protected:
    // http server
    HiveNS::Sync* m_pReceiveLock;
    moodycamel::ConcurrentQueue<HttpData> m_rcvqueue;
    moodycamel::ConcurrentQueue<CurlData> m_curlqueue;
    // HttpServer
    std::map<std::string, std::map<std::string, std::function<void(HttpData&& data)>>> m_http_svr_handle;

    std::map<std::int32_t, std::function<void(std::string&, bool)>> m_curl_rsp_cb;


protected:
    std::map<std::int32_t, std::function<int(int)>> m_timer_handler;
    std::map<std::int32_t, std::function<void(MsgData&&)>> m_msg_handler;

protected:
    moodycamel::ConcurrentQueue<MsgData> m_msgqueue;
    moodycamel::ConcurrentQueue<int> m_timerqueue;

private:
    moodycamel::LightweightSemaphore m_pSem;
    std::unique_ptr<std::thread> m_pEventHandleThread;
    std::atomic_bool m_eventThreadRunState;
    
public:
    int m_port = 0;
    std::string m_http_pre_path = "";
};


#endif  // __H_MSG_COMPONENT_H__
